package pl.edu.agh.mguesser.game.listener;

import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import pl.edu.agh.mguesser.game.GameFlow;

/**
 * @author keiran
 */
@Service
public class StartGameMediator {

    @Autowired
    private ApplicationContext applicationContext;
    
    private BeanProvider beanProvider = new SpringBasedBeanProvider();
    
    public void injectListeners(GameFlow gameFlow) {
        // TODO: polymorphism
        injectGameStartedListeners(gameFlow);
        injectNewRoundListener(gameFlow);
        injectUserChangedListener(gameFlow);
        injectStopRequestListener(gameFlow);
        injectTimeTickingListener(gameFlow);
        injectSongRevealedListener(gameFlow);
        injectAnswerRequiredListener(gameFlow);
        injectScoreChangedListener(gameFlow);
        injectGameDoneListeners(gameFlow);
    }

    private void injectGameStartedListeners(GameFlow gameFlow) {
        Collection<GameStartedListener> gameStartedListeners
                = beanProvider.getBeansOfType(GameStartedListener.class);
        for(GameStartedListener gameStartedListener : gameStartedListeners) {
            gameFlow.addGameStartedListener(gameStartedListener);
        }
    }

    private void injectNewRoundListener(GameFlow gameFlow) {
        Collection<NewRoundListener> newRoundListeners
                = beanProvider.getBeansOfType(NewRoundListener.class);
        for(NewRoundListener newRoundListener : newRoundListeners) {
            gameFlow.setNewRoundListener(newRoundListener);
        }
    }

    private void injectUserChangedListener(GameFlow gameFlow) {
        Collection<UserChangedListener> userChangedListeners
                = beanProvider.getBeansOfType(UserChangedListener.class);
        for(UserChangedListener userChangedListener : userChangedListeners) {
            gameFlow.setUserChangedListener(userChangedListener);
        }
    }

    private void injectStopRequestListener(GameFlow gameFlow) {
        Collection<StopRequestListener> stopRequestListeners
                = beanProvider.getBeansOfType(StopRequestListener.class);
        for(StopRequestListener stopRequestListener : stopRequestListeners) {
            gameFlow.setStopRequestListener(stopRequestListener);
        }
    }

    private void injectTimeTickingListener(GameFlow gameFlow) {
        Collection<TimeTickingListener> timeTickingListeners
                = beanProvider.getBeansOfType(TimeTickingListener.class);
        for(TimeTickingListener timeTickingListener : timeTickingListeners) {
            gameFlow.setTimeTickingListener(timeTickingListener);
        }
    }

    private void injectSongRevealedListener(GameFlow gameFlow) {
        Collection<SongRevealedListener> songRevealedListeners
                = beanProvider.getBeansOfType(SongRevealedListener.class);
        for(SongRevealedListener songRevealedListener : songRevealedListeners) {
            gameFlow.setSongRevealedListener(songRevealedListener);
        }
    }

    private void injectAnswerRequiredListener(GameFlow gameFlow) {
        Collection<AnswerRequiredListener> answerRequiredListeners
                = beanProvider.getBeansOfType(AnswerRequiredListener.class);
        for(AnswerRequiredListener answerRequiredListener : answerRequiredListeners) {
            gameFlow.setAnswerRequiredListener(answerRequiredListener);
        }
    }

    private void injectScoreChangedListener(GameFlow gameFlow) {
        Collection<ScoreChangedListener> scoreChangedListeners
                = beanProvider.getBeansOfType(ScoreChangedListener.class);
        for(ScoreChangedListener scoreChangedListener : scoreChangedListeners) {
            gameFlow.setScoreChangedListener(scoreChangedListener);
        }
    }

    private void injectGameDoneListeners(GameFlow gameFlow) {
        Collection<GameDoneListener> gameDoneListeners
                = beanProvider.getBeansOfType(GameDoneListener.class);
        for(GameDoneListener gameDoneListener : gameDoneListeners) {
            gameFlow.addGameDoneListener(gameDoneListener);
        }
    }
    
    public interface BeanProvider {
        <T> Collection<T> getBeansOfType(Class<T> type);
    }
    
    private class SpringBasedBeanProvider implements BeanProvider {

        @Override
        public <T> Collection<T> getBeansOfType(Class<T> type) {
            return applicationContext.getBeansOfType(type).values();
        }
        
    }

    void setBeanProvider(BeanProvider beanProvider) {
        this.beanProvider = beanProvider;
    }
    
}
